package org.gdstash.db;

import java.sql.Blob;
import java.util.LinkedList;
import java.util.List;
import java.sql.ResultSet;
import java.sql.PreparedStatement;
import java.sql.Statement;
import java.sql.Connection;
import java.sql.SQLException;
import org.gdstash.util.GDMsgLogger;
import org.gdstash.util.GDMsgFormatter;
import org.gdstash.file.ARZRecord;
import java.util.concurrent.ConcurrentHashMap;

public class DBCaravanWindow
{
    private static final String TABLE_NAME = "GDC_CARAVAN_WINDOW";
    private static final int ROW_RECORD_ID = 1;
    private static final int ROW_HEIGHT = 2;
    private static final int ROW_WIDTH = 3;
    private static final int ROW_X_POS = 4;
    private static final int ROW_Y_POS = 5;
    private static ConcurrentHashMap<String, DBCaravanWindow> hashBuffer;
    private String recordID;
    private int height;
    private int width;
    private int xPos;
    private int yPos;
    
    public DBCaravanWindow() {
        this.recordID = null;
    }
    
    public DBCaravanWindow(final ARZRecord record) {
        this();
        this.recordID = record.getFileName();
        this.height = record.getYSize();
        this.width = record.getXSize();
        this.xPos = record.getXOffset();
        this.yPos = record.getYOffset();
    }
    
    public int getHeight() {
        return this.height;
    }
    
    public int getWidth() {
        return this.width;
    }
    
    public int getXPos() {
        return this.xPos;
    }
    
    public int getYPos() {
        return this.yPos;
    }
    
    public static void clearBuffer() {
        DBCaravanWindow.hashBuffer.clear();
    }
    
    public static void createTable() throws SQLException {
        final String dropTable = "DROP TABLE GDC_CARAVAN_WINDOW";
        final String createTable = "CREATE TABLE GDC_CARAVAN_WINDOW (RECORD_ID        VARCHAR(256) NOT NULL, HEIGHT           INTEGER, WIDTH            INTEGER, X_POS            INTEGER, Y_POS            INTEGER, PRIMARY KEY (RECORD_ID))";
        try (final Connection conn = GDDBData.getConnection()) {
            final boolean auto = conn.getAutoCommit();
            conn.setAutoCommit(false);
            try (final Statement st = conn.createStatement()) {
                if (GDDBUtil.tableExists(conn, "GDC_CARAVAN_WINDOW")) {
                    st.execute(dropTable);
                }
                st.execute(createTable);
                st.close();
                conn.commit();
            }
            catch (SQLException ex) {
                conn.rollback();
                final Object[] args = { "GDC_CARAVAN_WINDOW" };
                final String msg = GDMsgFormatter.format(GDMsgFormatter.rbMsg, "ERR_CREATE_TABLE", args);
                GDMsgLogger.addError(msg);
                throw ex;
            }
            finally {
                conn.setAutoCommit(auto);
            }
        }
    }
    
    public static void insert(final ARZRecord record) throws SQLException {
        final DBCaravanWindow entry = get(record.getFileName());
        if (entry != null) {
            return;
        }
        final DBCaravanWindow cw = new DBCaravanWindow(record);
        final String insertBitmap = "INSERT INTO GDC_CARAVAN_WINDOW VALUES (?,?,?,?,?)";
        try (final Connection conn = GDDBData.getConnection()) {
            final boolean auto = conn.getAutoCommit();
            conn.setAutoCommit(false);
            try (final PreparedStatement ps = conn.prepareStatement(insertBitmap)) {
                ps.setString(1, cw.recordID);
                ps.setInt(2, cw.height);
                ps.setInt(3, cw.width);
                ps.setInt(4, cw.xPos);
                ps.setInt(5, cw.yPos);
                ps.executeUpdate();
                ps.close();
                conn.commit();
            }
            catch (SQLException ex) {
                conn.rollback();
                final Object[] args = { record.getFileName(), "GDC_CARAVAN_WINDOW" };
                final String msg = GDMsgFormatter.format(GDMsgFormatter.rbMsg, "ERR_INS_TABLE_BY_ID", args);
                GDMsgLogger.addLowError(msg);
                GDMsgLogger.addLowError(ex);
            }
            finally {
                conn.setAutoCommit(auto);
            }
        }
        catch (SQLException ex2) {
            throw ex2;
        }
    }
    
    public static DBCaravanWindow get(final String recordID) {
        DBCaravanWindow cw = null;
        cw = DBCaravanWindow.hashBuffer.get(recordID);
        if (cw == null) {
            cw = getDB(recordID);
        }
        return cw;
    }
    
    private static DBCaravanWindow getDB(final String recordID) {
        DBCaravanWindow cw = null;
        final String command = "SELECT * FROM GDC_CARAVAN_WINDOW WHERE RECORD_ID = ?";
        try (final Connection conn = GDDBData.getConnection();
             final PreparedStatement ps = conn.prepareStatement(command)) {
            ps.setString(1, recordID);
            try (final ResultSet rs = ps.executeQuery()) {
                final List<DBCaravanWindow> list = wrap(rs);
                if (list.isEmpty()) {
                    cw = null;
                }
                else {
                    cw = list.get(0);
                }
                conn.commit();
            }
            catch (SQLException ex) {
                throw ex;
            }
        }
        catch (SQLException ex2) {
            final Object[] args = { recordID, "GDC_CARAVAN_WINDOW" };
            final String msg = GDMsgFormatter.format(GDMsgFormatter.rbMsg, "ERR_READ_TABLE_BY_ID", args);
            GDMsgLogger.addError(msg);
            GDMsgLogger.addError(ex2);
        }
        return cw;
    }
    
    private static List<DBCaravanWindow> wrap(final ResultSet rs) throws SQLException {
        final LinkedList<DBCaravanWindow> list = new LinkedList<DBCaravanWindow>();
        final Blob blob = null;
        while (rs.next()) {
            final DBCaravanWindow cw = new DBCaravanWindow();
            cw.recordID = rs.getString(1);
            final DBCaravanWindow buff = DBCaravanWindow.hashBuffer.get(cw.recordID);
            if (buff != null) {
                list.add(buff);
            }
            else {
                cw.height = rs.getInt(2);
                cw.width = rs.getInt(3);
                cw.xPos = rs.getInt(4);
                cw.yPos = rs.getInt(5);
                list.add(cw);
                DBCaravanWindow.hashBuffer.put(cw.recordID, cw);
            }
        }
        return list;
    }
    
    static {
        DBCaravanWindow.hashBuffer = new ConcurrentHashMap<String, DBCaravanWindow>();
    }
}
